<?php
/**
 * @author Patrick
 *
 */
class EPMenuManager extends CApplicationComponent {

	const POS_BEGIN=0;
	const POS_LEADING=1;
	const POS_MAIN=2;
	const POS_ADDITION=3;
	const POS_END=4;

	private $_menus=array();
	private $_ms=array();
	private $_renderer;
	private $_parser;
	private $_processors=array();
	private $_defaultMenuId;

	public $renderer=array('class'=>'ext.epmenu.renderer.EPMenuListRenderer');
	public $parser=array('class'=>'ext.epmenu.parser.EPMenuArrayParser');
	public $processors=array();
	public $defaultCssPrefix='epmenu_';
	public $menuIdPrefix='epmenu_';


	public function init(){
		parent::init();
		Yii::import('ext.epmenu.EPMenuItem');
		Yii::import('ext.epmenu.EPMenuList');
		$this->_parser=Yii::createComponent($this->parser);
		$this->_renderer=Yii::createComponent($this->renderer);
		$needProcess=!empty($this->processors);

		if($needProcess){
			foreach ($this->processors as $key=>$processorConfig) {
				$processor=Yii::createComponent($processorConfig);
				$this->_processors[$key]=$processor;
			}
		}

		foreach($this->_menus as $menuId=>$value){
			$menu=new EPMenuList();
			$menu->menuId=$this->menuIdPrefix.$menuId;
			$menu->cssPrefix=$this->defaultCssPrefix;
			$this->_parser->parse($value,$menu);
			
			$this->_ms[$menuId]=$menu;
			if($needProcess){
				foreach ($this->_processors as $processor) {
					$processor->getEnabled() && $processor->afterParse($menu);
				}
			}
			if($this->_defaultMenuId===NULL){
				$this->_defaultMenuId=$menuId;
			}
		}
	}
	
	public function __call($name,$parameters){
		$offset=stripos($name,'menu');
		if($offset){
			$menuId=substr($name,0,$offset);
			if($this->menuExist($menuId)){
				$return = isset($parameters[0])?$parameters[0]:false;
				return $this->renderMenu($menuId,$return);
			}
		}


		return parent::__call($name,$parameters);
	}


	public function getMenu($menuId){
		if($this->menuExist($menuId)){
			return $this->_ms[$menuId];
		}
		return NULL;
	}

	public function menuExist($menuId){
		return isset($this->_ms[$menuId]);
	}

	public function setMenus($menus){
		$this->_menus=$menus;
	}

	public function renderMenu($menuId,$return=false){
		if(!isset($this->_ms[$menuId])){
			return NULL;
		}
		$menuList=$this->_ms[$menuId];
		foreach ($this->_processors as $processor) {
			$processor->getEnabled() && $processor->beforeRender($menuList);
		}
		$renderResult= $this->_renderer->render($this->_ms[$menuId]);
		foreach ($this->_processors as $processor) {
			$processor->getEnabled() && $processor->afterRender($menuList);
		}
		if($return){
			return $renderResult;
		}
		echo $renderResult;
	}

	public function parseInto($data,$menu){
		if(is_string($menu)&&$this->menuExist($menu)){
			$menu=$this->getMenu($menu);
		}
		if(!is_object($menu)){
			return NULL;
		}
		$this->_parser->parse($data,$menu);
	}

	public function renderDefaultMenu($return=false){
		return $this->renderMenu($this->_defaultMenuId,$return);
	}

	public function getDefaultMenu(){
		return $this->getMenu($this->_defaultMenuId);
	}

	public function enableProcessor($processorId){
		if(!isset($this->_processors[$key])){
			return;
		}
		$processor=$this->_processors[$key];
		$processor->setEnabled(true);
	}

	public function disableProcessor($processorId){
		if(!isset($this->_processors[$key])){
			return;
		}
		$processor=$this->_processors[$key];
		$processor->setEnabled(false);
	}
}

abstract class EPMenuRenderer extends CComponent{
	public function init($params){

	}
	public abstract function render($root);
}

abstract class EPMenuParser extends CComponent{
	public function init($params){

	}
	public abstract function parse($data,&$root);
}

abstract class EPMenuProcessor extends CComponent{
	private $_enabled=true;

	public function afterParse($menuList){
	}

	public function beforeRender($menuList){
	}

	public function afterRender($menuList){
	}
	public function setEnabled($enabled){
		$this->_enabled=$enabled;
	}
	public function getEnabled(){
		return $this->_enabled;
	}
}
